package debtbundler.presentation.balancesheeteditor;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JTextField;

import debtbundler.domain.entity.Person;
import debtbundler.presentation.VAlignment;
import debtbundler.presentation.basecomponents.SelectableDomainEditorImpl;
import debtbundler.presentation.utils.IconConstants;
import debtbundler.presentation.utils.UIUtils;

public class PersonEditor extends SelectableDomainEditorImpl<Person> implements ActionListener {
	
	private static final long serialVersionUID = 1L;
	private static Logger logger = Logger.getLogger(PersonEditor.class.getName());
	
	protected Person person;
	
	protected VAlignment vAlignment;
	protected JLabel nameFieldLabel;
	protected JTextField nameField;
	
	
	protected PersonEditor(Person person) {
		this(person, VAlignment.CENTER);
	}
	
	protected PersonEditor(Person person, VAlignment vAlignment) {
		super();
		
		if (person == null) {
			throw new IllegalArgumentException("Null person not allowed"); 
		}
		this.person = person;
		this.setLayout( new BoxLayout(this, BoxLayout.PAGE_AXIS) );
		createGUI();
	}	
	
	protected void createGUI() {
		logger.log(Level.FINE, "Creating GUI for {0}", this);
				
		nameField = new JTextField();
		nameField.setMaximumSize( new Dimension(nameField.getMaximumSize().width, nameField.getPreferredSize().height) );
		nameField.addActionListener(this);
		nameFieldLabel = new JLabel(UIUtils.getImageIcon(IconConstants.PERSON_16));
		nameFieldLabel.setLabelFor(nameField);

		setVerticalAlignment(vAlignment); // Layout
		refreshDomainFields();
	}
	
	/**
	 * Sets the vertical alignment of fields in this component.
	 * 
	 * @param vAlignment	the vertical alignment
	 */
	public void setVerticalAlignment(VAlignment vAlignment) {
		logger.log(Level.FINE, "Setting vertical alignment {0} for {1}", new Object[]{vAlignment, this});
		
		this.vAlignment = vAlignment != null ? vAlignment : VAlignment.CENTER;
		
		removeAll();
		
		if (vAlignment == VAlignment.BOTTOM || vAlignment == VAlignment.CENTER) {
			this.add(Box.createVerticalGlue());
		}
		
		Box nameBox = Box.createHorizontalBox();
		nameBox.add(nameFieldLabel);
		nameBox.add(Box.createRigidArea(new Dimension(6, 0)));
		nameBox.add(nameField);
		nameBox.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
		add(nameBox);
		
		if (vAlignment == VAlignment.TOP || vAlignment == VAlignment.CENTER) {
			add(Box.createVerticalGlue());
		}	
		
		revalidate();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		logger.log(Level.FINE, "Performing command {0} in {1}", new Object[]{e.getActionCommand(), this});
		
		if (e.getSource() == nameField) {
			setPersonName();
		}
	}

	@Override
	public void refreshDomainFields() {
		logger.log(Level.FINE, "Refreshing domain fields in {0}", this);
		
		nameField.setText( person.getName() );
	}

	@Override
	public Person getDomainComponent() {
		return this.person;
	}

	@Override
	public void focusLost(FocusEvent e) {
		logger.log(Level.FINER, "Focus lost by {0}", e.getComponent());
		
		// Must commit value when focus lost
		if (e.getComponent() == nameField) {
			setPersonName();
		}
		
		super.focusLost(e);
	}
	
	private void setPersonName() {
		if (!person.getName().equals(nameField.getText())) {
			person.setName(nameField.getText());
			fireDomainValueModified();
		}
	}
	
	/**
	 * If <code>enabled == false</code> sets the input fields in this editor 
	 * as read-only. Otherwise sets them editable. 
	 */
	@Override
	public void setEnabled(boolean enabled) {
		super.setEnabled(enabled);
		nameField.setEditable(enabled);
	}
	
	@Override
	public String toString() {
		return "Person editor for " + person;
	}	
}
